#include "stdafx.h"

#include "thermal_calc_model.h"


namespace blue_sky
{
	template <class strategy_t>
	int thermal_calc_model<strategy_t>::get_n_sec_vars (int n_phases){
		if (n_phases > 1)
			return 2;
		else
			return 1;
	}

	/**
	* \brief  'default' ctor for calc_model
	* \param  param additional params for calc_model
	* */
	template <class strategy_t>
	thermal_calc_model<strategy_t>::thermal_calc_model (bs_type_ctor_param param)
		: base_t(param)
	{	  
		//typedef thermal_calc_model_data <strategy_t>              data_t;                   //!< calc_model data, each instance for one mesh cell
		//typedef typename strategy_t::template vec <data_t>::type data_array_t;      //!< array of calc_model_data values, each value for one mesh cell
		//data = data_array_t();
	}

	/**
	* \brief  copy-ctor for calc_model
	* \param  src calc_model instance
	* */
	template <class strategy_t>
	thermal_calc_model<strategy_t>::thermal_calc_model (const this_t & src)
		: bs_refcounter (src), base_t(src)
	{
		if (&src != this)
			*this = src;
	}

	template <class strategy_t>
	thermal_calc_model<strategy_t>::~thermal_calc_model ()
	{
	}

	template <class strategy_t>
	int thermal_calc_model<strategy_t>::init_main_arrays (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh)
	{		
		temperature.resize(mesh->get_n_active_elements());
		thermal_data.resize(mesh->get_n_active_elements());		
		thermal_prev_niter_data_.temperature.resize(mesh->get_n_active_elements());
		thermal_old_data_.temperature.resize(mesh->get_n_active_elements());
		if(base_t::init_main_arrays(input_data,mesh) < 0)
			return -1;
		return 0;
	}

	template <class strategy_t>
	int thermal_calc_model<strategy_t>::set_initial_data (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh)
	{
		if(base_t::set_initial_data(input_data,mesh) < 0)
			return -1;
		if (init_temperature(input_data, mesh) < 0)
			return -1;
		return 0;
	}

	template <class strategy_t>
	int thermal_calc_model<strategy_t>::init_temperature (const sp_idata_t &input_data, const sp_mesh_iface_t &mesh)
	{
		convert_arrays (mesh->get_n_active_elements (), mesh->get_int_to_ext (), temperature, input_data->get_float_non_empty_array("TEMPERATURE"));		
		return 0;
	}

	template <typename strategy_t>
	int
	thermal_calc_model<strategy_t>::new_simple_get_cell_solution (const double mult, int istart_linear_search,
      const sp_mesh_iface_t &msh,const sp_jacobian_matrix_t &jacobian)
	{
		int result = base_t::new_simple_get_cell_solution(mult, istart_linear_search, msh, jacobian);
		item_t *sol_temperature              = 0;
		if (!istart_linear_search)
		{
			sol_temperature              = &temperature[0];
		}
		else
		{
			sol_temperature              = &thermal_prev_niter_data_.temperature[0];
		}
		index_t n                   = msh->get_n_active_elements ();
		const item_array_t &sec_sol = jacobian->get_sec_solution ();
		
		typename i_vector_type::iterator it;
		i_vector_type non_boundary_cells = boundary_builder_->get_non_boundary_cells();
		for (it = non_boundary_cells.begin(); it < non_boundary_cells.end(); ++it){
			index_t cell = *it;
			item_t dto = 0;
			dto = sec_sol[cell];

			item_t dto_mult = dto * mult;
			temperature[cell] = sol_temperature[cell] + dto_mult;
		}
		return result;
	}

	template <typename strategy_t>
	void
	thermal_calc_model<strategy_t>:: set_boundary_builder(sp_boundary_builder boundary_builder){
		boundary_builder_ = boundary_builder;
	}


	BLUE_SKY_TYPE_STD_CREATE_T_DEF(thermal_calc_model, (class));
	BLUE_SKY_TYPE_STD_COPY_T_DEF(thermal_calc_model, (class));

	BLUE_SKY_TYPE_IMPL_T_EXT(1, (thermal_calc_model<base_strategy_fi>) , 1, (calc_model<base_strategy_fi>), "thermal_calc_model_fi", "thermal_calc_model_base-float-int", "Thermal_calc_model_base with float items and integer indexes", false);
	BLUE_SKY_TYPE_IMPL_T_EXT(1, (thermal_calc_model<base_strategy_di>) , 1, (calc_model<base_strategy_di>), "thermal_calc_model_di", "thermal_calc_model_base-double-int", "Thermal_calc_model_base with double items and integer indexes", false);
	BLUE_SKY_TYPE_IMPL_T_EXT(1, (thermal_calc_model<base_strategy_mixi>) , 1, (calc_model<base_strategy_mixi>), "thermal_calc_model_mixi", "thermal_calc_model_base-mix-int", "Thermal_calc_model_base with double items and integer indexes", false);

	bool thermal_calc_model_register_type(const blue_sky::plugin_descriptor &pd)
	{
		bool res = true;
		res &= BS_KERNEL.register_type (pd, thermal_calc_model<base_strategy_fi>::bs_type ());
		res &= BS_KERNEL.register_type (pd, thermal_calc_model<base_strategy_di>::bs_type ());
		res &= BS_KERNEL.register_type (pd, thermal_calc_model<base_strategy_mixi>::bs_type ());
		return res;
	}
}